package il.technion.cs236369.webserver;

import java.util.HashMap;

import org.apache.http.Header;
import org.apache.http.HttpResponse;

public class SessionManager
{
	private static HashMap<Integer, Session> sessions = new HashMap<Integer, Session>();
	private static Integer idCounter = new Integer(0);

	/**
	 * Initiates a session
	 * @param request
	 * @param response
	 * @return the session id in the request or a new one if unavailable
	 */
	public static Integer initiateSession(ExtendedHttpRequest request, HttpResponse response)
	{
		Integer id = null;
		Header cookieHeader = request.GetHttpRequest().getFirstHeader("Cookie");

		// if the request came with a cookie, start breaking it down
		if (cookieHeader != null) 
		{
			// take all the cookie data
			String cookieString = cookieHeader.getValue();
			String[] cookieFields = cookieString.split(";");
			String idField = null, userField = null;
			
			for (String field : cookieFields)
			{
				field = field.trim();
				String[] keyValue = field.split("=");
				if (keyValue[0].equalsIgnoreCase("user"))
				{
					userField = keyValue[1];
				}
				if (keyValue[0].equalsIgnoreCase("id"))
				{
					idField = keyValue[1];
				}
			}

			// if the cookie contains user info, draw the session by that
			if (userField != null)
			{
				synchronized (sessions)
				{
					for (Integer i : sessions.keySet())
					{
						if (((String)sessions.get(i).GetParameter("user")).equalsIgnoreCase(userField))
						{
							id = i;
							break;
						}
					}
				}
			}
			else 	// if not, get the session id from the cookie
			{
				id = new Integer(idField);
			}

			synchronized (sessions)
			{
				Session ses;
				// and if we have an id by this point and it's valid, return it
				if (id != null && (ses = sessions.get(id)) != null)
				{
					if (userField != null)
					{
						ses.SetParameter("user", userField);
					}
					return id;
				}
			}
		}

		// if there is no cookie header, create a new session id
		synchronized (sessions)
		{
			String[] params = request.GetPath().split("&");
			
			Session session = new Session();

			for (int i = 1; i < params.length; i++)
			{
				String[] keyValue = params[i].split("=");
				session.SetParameter(keyValue[0], keyValue[1]);
			}
			
			id = idCounter = new Integer(idCounter.intValue() + 1);
			sessions.put(id, session);
		}

		return id;
	}

	public static Session getSession(Integer id)
	{
		synchronized (sessions)
		{
			return sessions.get(id);
		}
	}

	public static void invalidateSession(Integer id)
	{
		getSession(id).invalidate();
		synchronized (sessions)
		{
			sessions.remove(id);
		}
	}

}
